package com.sudworth.repository.untils;

import android.graphics.Bitmap;
import android.text.TextUtils;
import android.util.Base64;

import androidx.annotation.NonNull;

import com.violet.constlib.annotations.ConvertMap;
import com.violet.constlib.annotations.Ignore;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Convert {

    public static <S, R> List<R> convertToResultList(@NonNull List<S> source, @NonNull Class<R> rClass) {
        List<R> results = new ArrayList<R>();
        if(source == null)
            return results;
        try {
            for (S one : source) {
                Constructor<R> constructor = rClass.getConstructor(one.getClass());
                results.add(constructor.newInstance(one));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return results;
    }

    public static <S, R> List<R> convertToResultList(@NonNull List<S> source, @NonNull Class<S> sClass, @NonNull Class<R> rClass) {
        List<R> results = new ArrayList<R>();
        if(source == null)
        return results;
        try {
            for (S one : source) {
                Constructor<R> constructor = rClass.getConstructor(sClass);
                results.add(constructor.newInstance(one));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return results;
    }

    public static @NonNull <S> Map<String, Object> convertToMap(S s) {
        Map<String, Object> map = new HashMap<>();
        Field[] declaredFields = s.getClass().getDeclaredFields();
        if(declaredFields.length == 0) return map;
        for(Field field: declaredFields) {
            field.setAccessible(true);
            Ignore annotation = field.getAnnotation(Ignore.class);
            if(annotation != null) continue;
            ConvertMap convertMap = field.getAnnotation(ConvertMap.class);
            if(convertMap == null) continue;
            String key = field.getName();
            String fKey = convertMap.key();
            if(!TextUtils.isEmpty(fKey)) {
                key = fKey;
            }
            try {
                Object o = field.get(s);
                map.put(key, o);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return map;
    }

    /**
     * 文件转base64字符串
     *
     * @param file
     * @return
     */
    public static String fileToBase64(File file) {
        String base64 = null;
        InputStream in = null;
        try {
            in = new FileInputStream(file);
            byte[] bytes = new byte[in.available()];
            int length = in.read(bytes);
            base64 = Base64.encodeToString(bytes, 0, length, Base64.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return base64;
    }

    public static String md5(String str) {
        MessageDigest md5 = null;
        try {
            md5 = MessageDigest.getInstance("MD5");
            byte[] bytes = md5.digest(str.getBytes());
            StringBuilder result = new StringBuilder();
            for (byte b : bytes) {
                String temp = Integer.toHexString(b & 0xff);
                if (temp.length() == 1) {
                    temp = "0" + temp;
                }
                result.append(temp);
            }
            return result.toString();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * @param bitmap
     * @param format
     * @param quality
     * @param minKB 单位KB，千字节，低于这么值，不缩放
     * @param fileLength 文件大小
     * @return
     */
    public static String bitmap2Base64(Bitmap bitmap, Bitmap.CompressFormat format, int quality, int minKB, long fileLength) {
        // 要返回的字符串
        String reslut = null;
        ByteArrayOutputStream baos = null;
        try {
            if (bitmap != null) {
                baos = new ByteArrayOutputStream();
                /**
                 * 压缩只对保存有效果bitmap还是原来的大小
                 */
//                bitmap.compress(Bitmap.CompressFormat.JPEG, 30, baos);
                if(minKB * 1024 >= fileLength) {
                    quality = 100;
                }
                bitmap.compress(format, quality, baos);
                baos.flush();
                baos.close();
                // 转换为字节数组
                byte[] byteArray = baos.toByteArray();
                // 转换为字符串
                reslut = Base64.encodeToString(byteArray, 0, byteArray.length, Base64.DEFAULT);
            } else {
                return null;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (baos != null) {
                    baos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return reslut;
    }

    private static int getBitmapSize(Bitmap bitmap) {
        return bitmap.getAllocationByteCount();
    }

    /**
     * 判断字符串使用同时包含数字和英文
     * @param str
     * @return true 代表不满足，false 标识满足
     */
    public static boolean isLetterDigit(String str) {
        boolean isDigit = false;//定义一个boolean值，用来表示是否包含数字
        boolean isLetter = false;//定义一个boolean值，用来表示是否包含字母
        for (int i = 0; i < str.length(); i++) {
            if (Character.isDigit(str.charAt(i))) {   //用char包装类中的判断数字的方法判断每一个字符
                isDigit = true;
            }
            if (Character.isLetter(str.charAt(i))) {  //用char包装类中的判断字母的方法判断每一个字符
                isLetter = true;
            }
        }
        String regex = "^[a-zA-Z0-9]+$";
        return isDigit && isLetter && str.matches(regex);
    }
}

